{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mixed Distance Functions for  k-Nearest Neighbor\n",
    "\n",
    "\n",
    "This function shows how to use different distance metrics on different features for kNN.\n",
    "\n",
    "#### Data:\n",
    "----------x-values-----------\n",
    "* CRIM   : per capita crime rate by town\n",
    "* ZN     : prop. of res. land zones\n",
    "* INDUS  : prop. of non-retail business acres\n",
    "* CHAS   : Charles river dummy variable\n",
    "* NOX    : nitrix oxides concentration / 10 M\n",
    "* RM     : Avg. # of rooms per building\n",
    "* AGE    : prop. of buildings built prior to 1940\n",
    "* DIS    : Weighted distances to employment centers\n",
    "* RAD    : Index of radian highway access\n",
    "* TAX    : Full tax rate value per $10k\n",
    "* PTRATIO: Pupil/Teacher ratio by town\n",
    "* B      : 1000*(Bk-0.63)^2, Bk=prop. of blacks\n",
    "* LSTAT  : % lower status of pop\n",
    "\n",
    "------------y-value-----------\n",
    "* MEDV   : Median Value of homes in $1,000's"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import requests\n",
    "from tensorflow.python.framework import ops\n",
    "ops.reset_default_graph()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "housing_url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data'\n",
    "housing_header = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']\n",
    "cols_used = ['CRIM', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'TAX', 'PTRATIO', 'B', 'LSTAT']\n",
    "num_features = len(cols_used)\n",
    "housing_file = requests.get(housing_url)\n",
    "housing_data = [[float(x) for x in y.split(' ') if len(x)>=1] for y in housing_file.text.split('\\n') if len(y)>=1]\n",
    "\n",
    "y_vals = np.transpose([np.array([y[13] for y in housing_data])])\n",
    "x_vals = np.array([[x for i,x in enumerate(y) if housing_header[i] in cols_used] for y in housing_data])\n",
    "\n",
    "## Min-Max Scaling\n",
    "x_vals = (x_vals - x_vals.min(0)) / x_vals.ptp(0)\n",
    "\n",
    "## Create distance metric weight matrix weighted by standard deviation\n",
    "weight_diagonal = x_vals.std(0)\n",
    "weight_matrix = tf.cast(tf.diag(weight_diagonal), dtype=tf.float32)\n",
    "\n",
    "# Split the data into train and test sets\n",
    "np.random.seed(13)  #make results reproducible\n",
    "train_indices = np.random.choice(len(x_vals), round(len(x_vals)*0.8), replace=False)\n",
    "test_indices = np.array(list(set(range(len(x_vals))) - set(train_indices)))\n",
    "x_vals_train = x_vals[train_indices]\n",
    "x_vals_test = x_vals[test_indices]\n",
    "y_vals_train = y_vals[train_indices]\n",
    "y_vals_test = y_vals[test_indices]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Declare k-value and batch size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "k = 4\n",
    "batch_size=len(x_vals_test)\n",
    "\n",
    "# Placeholders\n",
    "x_data_train = tf.placeholder(shape=[None, num_features], dtype=tf.float32)\n",
    "x_data_test = tf.placeholder(shape=[None, num_features], dtype=tf.float32)\n",
    "y_target_train = tf.placeholder(shape=[None, 1], dtype=tf.float32)\n",
    "y_target_test = tf.placeholder(shape=[None, 1], dtype=tf.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Declare weighted distance metric\n",
    "# Weighted - L2 = sqrt((x-y)^T * A * (x-y))\n",
    "subtraction_term =  tf.subtract(x_data_train, tf.expand_dims(x_data_test,1))\n",
    "first_product = tf.matmul(subtraction_term, tf.tile(tf.expand_dims(weight_matrix,0), [batch_size,1,1]))\n",
    "second_product = tf.matmul(first_product, tf.transpose(subtraction_term, perm=[0,2,1]))\n",
    "distance = tf.sqrt(tf.matrix_diag_part(second_product))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Predict: Get min distance index (Nearest neighbor)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Batch #1 MSE: 18.847\n"
     ]
    }
   ],
   "source": [
    "top_k_xvals, top_k_indices = tf.nn.top_k(tf.negative(distance), k=k)\n",
    "x_sums = tf.expand_dims(tf.reduce_sum(top_k_xvals, 1),1)\n",
    "x_sums_repeated = tf.matmul(x_sums,tf.ones([1, k], tf.float32))\n",
    "x_val_weights = tf.expand_dims(tf.div(top_k_xvals,x_sums_repeated), 1)\n",
    "\n",
    "top_k_yvals = tf.gather(y_target_train, top_k_indices)\n",
    "prediction = tf.squeeze(tf.matmul(x_val_weights,top_k_yvals), axis=[1])\n",
    "\n",
    "# Calculate MSE\n",
    "mse = tf.div(tf.reduce_sum(tf.square(tf.subtract(prediction, y_target_test))), batch_size)\n",
    "\n",
    "# Calculate how many loops over training data\n",
    "num_loops = int(np.ceil(len(x_vals_test)/batch_size))\n",
    "\n",
    "for i in range(num_loops):\n",
    "    min_index = i*batch_size\n",
    "    max_index = min((i+1)*batch_size,len(x_vals_train))\n",
    "    x_batch = x_vals_test[min_index:max_index]\n",
    "    y_batch = y_vals_test[min_index:max_index]\n",
    "    predictions = sess.run(prediction, feed_dict={x_data_train: x_vals_train, x_data_test: x_batch,\n",
    "                                         y_target_train: y_vals_train, y_target_test: y_batch})\n",
    "    batch_mse = sess.run(mse, feed_dict={x_data_train: x_vals_train, x_data_test: x_batch,\n",
    "                                         y_target_train: y_vals_train, y_target_test: y_batch})\n",
    "\n",
    "    print('Batch #' + str(i+1) + ' MSE: ' + str(np.round(batch_mse,3)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n48Yxbty4suXLli3jF7/4xeqE37dv3zaR7MFdOmZWALvssgtPP/00CxcuZJtttuGII45g6NChLFq0\niNtvv53Ro0ez4447ctBBB7FixQoAbr31VoYMGcKOO+7Iddd9fHOyadOmcfzxxwOwZMkS9t9/f4YP\nH87w4cO57777OOOMM3jmmWcYMWIEp556KgsXLmTo0KFAdjL7qKOOYtiwYYwcOZJZs2at3uYBBxzA\n2LFjGTRoEKeddlou7eCEb2Yd2qpVq7jlllsYNmwYAE899RTHHnssjz32GD169OC8887jjjvu4OGH\nH6auro6LLrqId999l29/+9v84Q9/YM6cObzyyiuNbvuEE05g11135dFHH+Xhhx9m++2354ILLmDr\nrbdm7ty5/PjHP15j+Z///OdIYt68eUyfPp3x48evvvJm7ty5XH311cybN4+rr76aRYsW1bwtnPDN\nrENauXIlI0aMoK6ujv79+zNhwgQAttxyS0aNGgXA/fffz+OPP85OO+3EiBEjuOyyy3j++ed54okn\nGDhwIIMGDUIShx12WKN13HnnnRxzTHb7206dOtGrV69Gl6t3zz33rN7WkCFD2HLLLVmwIDu/scce\ne9CrVy+6du3Kdtttx/PPVz0mWtXch29mHVJpH36pHj16rH4eEYwZM4bp06evsUxj6+Vto402Wv28\nU6dOrFq1quZ1+AjfzApr1KhR3HvvvTz99NMAvP322yxYsIAhQ4awcOFCnnnmGYC1PhDq7bHHHlxy\nySUAfPjhhyxfvpyePXvy1ltvNbr8LrvswhVXXAHAggULeOGFF9hmm21qvVtl+QjfzHJXzWWUraFP\nnz5MmzaNQw45hPfeew+A8847j8GDBzN16lT23ntvunfvzi677NJoEr/44ouZOHEil156KZ06deKS\nSy5h9OjR7LTTTgwdOpSvfe1rHHfccauXP/bYYznmmGMYNmwYnTt3Ztq0aWsc2eetTd3Ttq6uLnwD\nFFvNl2W2W/Pnz2fbbbdt7TA6nMbaVdKciKirZn136ZiZFYQTvplZQTjhm5kVhBO+mVlBOOGbmRWE\nE76ZWUH4Onwzy1+lS2ybo8rLcm+44Qb2339/5s+fz5AhQ8ouN23aNPbcc0/69u3brHBKh09uy3yE\nb2Yd1vTp09l5553L/lK23rRp03jppZdaKKrW44RvZh3SihUruOeee7j00ku56qqrVs+/8MILGTZs\n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\nemFq2bL7K7x2zTbr/AqFB5YtKfv+AkZPmFy2rNx7bNKYwRXiaKZK+7b7mbWvLwcV/yfzaLM2LPeT\ntpI2Bq4FToqINxuWR8TUiKiLiLo+ffrkHY6ZWWHlmvAldSFL9ldExHV51mVmZpXleZWOgEuB+RFx\nUV71mJlZdfI8wt8JOBz4sqS56bFXjvWZmVkFuZ20jYh7AOW1fTMzaxr/0tbMrCCc8M3MCsIJ38ys\nIJzwzcwKwgnfzKwgnPDNzArCCd/MrCCc8M3MCsIJ38ysIJzwzcwKwgnfzKwgnPDNzArCCd/MrCCc\n8M3MCsIJ38ysIJzwzcwKwgnfzKwgcrvjVUc26oWpZcvu7z+xbNnsZ5fmEY7VSHNfn4rr9W9eLFNm\nLihbVv79N7l5lc06v3nrVdC8+GH0hNrvw6gXKrw+s3o3OnvKqgPLrjJpzOBmxdEW+AjfzKwgnPDN\nzArCCd/MrCCc8M3MCsIJ38ysIJzwzcwKwgnfzKwgnPDNzArCCd/MrCCc8M3MCsIJ38ysIJzwzcwK\nwgnfzKwgnPDNzArCCd/MrCCc8M3MCsIJ38ysIJzwzcwKwgnfzKwgck34ksZKelLS05LOyLMuMzOr\nLLeEL6kT8HPga8B2wCGStsurPjMzqyzPI/zPA09HxLMR8T5wFbBvjvWZmVkFioh8Nix9AxgbEf8v\nTR8OfCEijm+w3ERgYprcBngyl4BazmbA660dRBvhtliT22NNbo+PrU9bbBkRfapZsHMzK6iZiJgK\nTG3tOGpF0kMRUdfacbQFbos1uT3W5Pb4WEu1RZ5dOi8CW5RM90vzzMysFeSZ8P8CDJI0UNKGwMHA\nTTnWZ2ZmFeTWpRMRqyQdD9wGdAJ+ExGP5VVfG9JhuqdqwG2xJrfHmtweH2uRtsjtpK2ZmbUt/qWt\nmVlBOOGbmRWEE34zSfqNpFcl/a1k3qaSZkp6Kv3dpDVjbEmStpA0S9Ljkh6TdGKaX7g2kdRV0oOS\nHk1t8b00v3BtUUpSJ0mPSLo5TRe2PSQtlDRP0lxJD6V5ubeHE37zTQPGNph3BvCniBgE/ClNF8Uq\n4F8jYjtgFHBcGkqjiG3yHvDliBgOjADGShpFMdui1InA/JLporfH7hExouT6+9zbwwm/mSLiz8Ab\nDWbvC1yWnl8G7NeiQbWiiHg5Ih5Oz98i+8fenAK2SWRWpMku6REUsC3qSeoH7A38umR2YdujjNzb\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1082945f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "# Plot prediction and actual distribution\n",
    "bins = np.linspace(5, 50, 45)\n",
    "\n",
    "plt.hist(predictions, bins, alpha=0.5, label='Prediction')\n",
    "plt.hist(y_batch, bins, alpha=0.5, label='Actual')\n",
    "plt.title('Histogram of Predicted and Actual Values')\n",
    "plt.xlabel('Med Home Value in $1,000s')\n",
    "plt.ylabel('Frequency')\n",
    "plt.legend(loc='upper right')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda env:tf-cpu]",
   "language": "python",
   "name": "conda-env-tf-cpu-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
